package com.amigo.online.provider.user.service.impl;

import java.time.Instant;
import java.util.ArrayList;
import java.util.List;

import javax.annotation.Resource;

import com.amigo.online.provider.user.service.UserService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.alibaba.fastjson.JSONObject;
import com.amigo.online.common.base.security.LocalUser;
import com.amigo.online.common.base.service.BaseService;
import com.amigo.online.common.core.response.StatusCode;
import com.amigo.online.common.param.RedisKey;
import com.amigo.online.common.param.dto.user.DeletePhotoDto;
import com.amigo.online.common.param.dto.user.ReplacePhotoDto;
import com.amigo.online.common.param.result.HobbyInfo;
import com.amigo.online.common.param.result.LocalUserInfo;
import com.amigo.online.common.param.result.PhotoInfo;
import com.amigo.online.common.param.result.UserInfo;
import com.amigo.online.provider.user.common.GlobalController;
import com.amigo.online.provider.user.common.RwRedisService;
import com.amigo.online.provider.user.exception.UserException;
import com.amigo.online.provider.user.mapper.UserHobbyMapper;
import com.amigo.online.provider.user.mapper.UserMapper;
import com.amigo.online.provider.user.mapper.UserPhotosMapper;
import com.amigo.online.provider.user.model.entity.User;
import com.amigo.online.provider.user.model.entity.UserHobby;
import com.amigo.online.provider.user.model.entity.UserPhotos;
import com.amigo.online.provider.user.mongo.dao.UserDao;
import com.amigo.online.provider.user.mongo.entity.UserEntity;
import com.amigo.online.provider.user.rocketmq.RocketMqUtil;
import com.amigo.online.provider.user.rocketmq.model.BaseMqSendModel;
import com.amigo.online.provider.user.service.TanService;
import com.amigo.online.provider.user.service.TokenManagerService;
import com.amigo.online.provider.user.util.ConvertUtil;


@Service
@Transactional(rollbackFor = Exception.class)
public class TanServiceImpl extends BaseService<User> implements TanService {

    /**
     * 探探功能已checked
     */
    public static final int TANTAN_STATUS_CHECKED = 1;

    /**
     * 探探功能未checked
     */
    public static final int TANTAN_STATUS_UNCHECKED = 0;

    @Resource
    private UserPhotosMapper userPhotosMapper;

    @Resource
    private UserMapper userMapper;

    @Resource
    private TokenManagerService tokenManagerService;

    @Resource
    private UserHobbyMapper userhobbyMapper;

    @Autowired
    private UserDao userDao;

    private static String user_key = RedisKey.USER_REDIS_KEY;

    @Autowired
    RwRedisService rwRedisService;

    @Autowired
    private UserService userService;

    private void send(Long id, String photo) {
        JSONObject g = new JSONObject();
        g.put("id", id);
        g.put("photo", photo);
        RocketMqUtil.send(new BaseMqSendModel.Builder()
                .beanName("FaceRecognition")
                .sendContentBean(g)
                .tag("opencv")
                .build());
    }

    private UserInfo getUserById(Long id) {
        User mysqlUser = userMapper.selectByPrimaryKey(id);
        //用户照片
        List<UserPhotos> list = userPhotosMapper.getListByUid(id);
        //用户爱好
        List<UserHobby> hobbylist = userhobbyMapper.findHobbyByUserId(id);
        if (mysqlUser == null) {
            throw new UserException(StatusCode.USER_EXCEPTION);
        }
        UserInfo userInfo = ConvertUtil.UserToUserInfo(mysqlUser);
        List<PhotoInfo> plist = ConvertUtil.UserPhotosToPhotoInfo(list);
        ArrayList<HobbyInfo> hobbyInfoList = ConvertUtil.HobbyToHobbyInfo(hobbylist);
        userInfo.setPhotos(plist);
        userInfo.setHobbylist(hobbyInfoList);
        return userInfo;
    }

    @Override
    public boolean openT() {
        UserInfo nowUser = GlobalController.getNowUser();
        Long id = nowUser.getId();
        User user = new User();
        user.setId(nowUser.getId());
        user.setOpenT(1);
        Long nowtime = System.currentTimeMillis() / 1000;
        user.setOpenTime(nowtime);
        userMapper.openT(user);
        UserInfo ui = (UserInfo) rwRedisService.opsForHashRead().get(user_key, id);
        if (ui == null) {
            //应该不是空  但是要做处理
            ui = getUserById(id);
        }
        ui.setOpenT(1);
        LocalUserInfo info = LocalUser.getUser();
        UserInfo us = info.getUser();
        us.setOpenT(1);
        info.setUser(us);
        tokenManagerService.updateUser(info);
        //更新用户信息
        rwRedisService.opsForHash().delete(user_key, id);
		
		/*
		 * 异步处理
		UserEntity users = userDao.getUserById(nowUser.getId());
		users.setOpenT(1);	
		userDao.updateUser(users);*/
        return true;
    }

    @Override
    public boolean closeT() {
        UserInfo nowUser = GlobalController.getNowUser();
        Long id = nowUser.getId();
        User user = new User();
        user.setId(nowUser.getId());
        user.setOpenT(0);
        Long nowtime = System.currentTimeMillis() / 1000;
        user.setCloseTime(nowtime);
        userMapper.closeT(user);
        UserInfo ui = (UserInfo) rwRedisService.opsForHashRead().get(user_key, id);
        if (ui == null) {
            //应该不是空  但是要做处理
            ui = getUserById(id);
        }
        ui.setOpenT(0);
        LocalUserInfo info = LocalUser.getUser();
        UserInfo us = info.getUser();
        us.setOpenT(0);
        info.setUser(us);
        tokenManagerService.updateUser(info);
        //更新用户信息
        rwRedisService.opsForHash().delete(user_key, id);
		
		/* 异步处理
		UserEntity users = userDao.getUserById(nowUser.getId());
		users.setOpenT(0);
		userDao.updateUser(users);*/

        return true;
    }

    @Override
    public PhotoInfo newUserPhoto(String photo, Integer firstImg, Integer sort) {
        if (photo == null) {
            throw new UserException(StatusCode.BAD_REQUEST);
        }
        UserInfo userInfo = GlobalController.getNowUser();
        UserPhotos userPhotos = new UserPhotos();
//        UserEntity user = userDao.getUserById(userInfo.getId());
//        if (user == null) {
//            throw new UserException(StatusCode.USER_EXCEPTION);
//        }
//		if(user.getOpenT() == 0) {
//			throw new UserException(StatusCode.USER_EXCEPTION);
//		}
        userPhotos.setUserId(userInfo.getId());
        userPhotos.setFirstImg(firstImg);
        userPhotos.setPhoto(photo);
        userPhotos.setSort(sort);
        userPhotos.setCreatedTime(Instant.now().getEpochSecond());
        userPhotos.setUpdatedTime(0L);
        userPhotos.setDeleted(0);
        userPhotos.setDeletedTime(0L);
        userPhotos.setChecked(TANTAN_STATUS_CHECKED);
        if (userPhotosMapper.insert(userPhotos) <= 0) {
            throw new UserException(StatusCode.UPLOAD_USER_PHOTO_FAILED);
        }
        PhotoInfo photoInfo = new PhotoInfo();
        BeanUtils.copyProperties(userPhotos, photoInfo);
        rwRedisService.opsForHash().delete(user_key, userInfo.getId());
        //更新mongoDB
        if (firstImg == 1) {
            //同时发消息给审核服务
///			send(p.getId(), p.getPhoto());
            Update update = new Update().set("checked", TANTAN_STATUS_CHECKED)
                    .set("firstImg", photo);
            userDao.updateUserInfo(userInfo.getId(), update);
        }
        return photoInfo;
    }

    @Override
    public List<PhotoInfo> deleteUserPhoto(DeletePhotoDto dto) {
        UserInfo user = GlobalController.getNowUser();
        UserInfo tempInfo = userService.getUserById(user.getId());
        Long photoId = dto.getId();
        UserPhotos userPhotos = userPhotosMapper.selectByPrimaryKey(photoId);
        List<UserPhotos> uplist = null;
        if (userPhotos == null) {
            logger.error("照片id传递异常{}", photoId);
            throw new UserException(StatusCode.USER_EXCEPTION);
        }
        if (userPhotos.getDeleted() == 1) {
            logger.error("这张照片已经被删除过，相册id:{}", photoId);
            return tempInfo.getPhotos();
        }
        if (tempInfo.getPhotos().size() <= 1) {
            throw new UserException(StatusCode.FORBIDDEN);
        }
        //删除的是第一张图片
        if (userPhotos.getFirstImg() == 1) {
            logger.info("删除的是第一张图片");
            userPhotos.setDeleted(1);
            userPhotosMapper.updateByPrimaryKey(userPhotos);
            uplist = userPhotosMapper.getListByUid(user.getId());
            //删除的是第一张  第二张变第一张
            if (uplist != null && uplist.size() > 0) {
                //删除第一张
                UserPhotos ups = uplist.get(0);
                ups.setFirstImg(1);
                uplist.set(0, ups);
                userPhotosMapper.updateByPrimaryKey(ups);
                UserEntity userEntity = userDao.getUserById(user.getId());
                String secondPhoto = tempInfo.getPhotos().get(1) != null ? tempInfo.getPhotos().get(1).getPhoto() : "";
                if (userEntity != null) {
                    //同时发消息给审核服务
///					send(ups.getId(), ups.getPhoto());
                    //把mongo的firstImg变成第二张
                    Update update = new Update().set("checked", TANTAN_STATUS_CHECKED)
                            .set("firstImg", secondPhoto);
                    userDao.updateUserInfo(user.getId(), update);
                }
                //把用户头像变成第二张
                User updateUser = new User();
                updateUser.setId(user.getId());
                updateUser.setAvatar(secondPhoto);
                logger.error("头像变成了:{}", secondPhoto);
                updateUser.setUpdatedTime(Instant.now().getEpochSecond());
                userMapper.updateByPrimaryKeySelective(updateUser);
            }
        } else {
            //非第一张相册
            logger.info("删除的是非第一张图片");
            userPhotos.setDeleted(1);
            userPhotos.setDeletedTime(Instant.now().getEpochSecond());
            userPhotosMapper.updateByPrimaryKey(userPhotos);
            uplist = userPhotosMapper.getListByUid(user.getId());
        }
        List<PhotoInfo> userPhotosToPhotoInfo = ConvertUtil.UserPhotosToPhotoInfo(uplist);
        tempInfo.setPhotos(userPhotosToPhotoInfo);
        rwRedisService.opsForHash().delete(user_key, user.getId());
        logger.info("删除成功");
        return userPhotosToPhotoInfo;
    }

    @Override
    public List<PhotoInfo> getUserPhotos() {
        Long userId = GlobalController.getNowUser().getId();
        UserInfo userInfo = userService.getUserById(userId);
        return userInfo.getPhotos();
    }

    /**
     * 相册排序
     * @param photoIds
     */
    @Override
    public List<PhotoInfo> updatePhotosSort(long[] photoIds) {
        if(photoIds != null && photoIds.length>0){
            User updateUser = new User();
            updateUser.setId(LocalUser.getUser().getUser().getId());
            UserPhotos userPhotos = userPhotosMapper.selectByPrimaryKey(photoIds[0]);
            userPhotos.setFirstImg(1);
            userPhotosMapper.updateByPrimaryKey(userPhotos);
            updateUser.setAvatar(userPhotos.getPhoto());
            updateUser.setUpdatedTime(Instant.now().getEpochSecond());
            userMapper.updateByPrimaryKeySelective(updateUser);


            Update update = new Update();
            update.set("avatar", userPhotos.getPhoto());
            userDao.updateUserInfo(updateUser.getId(),update);
            for (int i=0; i<photoIds.length;i++){
                userPhotosMapper.updatePhotoSort(photoIds[i],i);
            }
        }
        List<UserPhotos> uplist = userPhotosMapper.getListByUid(LocalUser.getUser().getUser().getId());
        List<PhotoInfo> userPhotosToPhotoInfo = ConvertUtil.UserPhotosToPhotoInfo(uplist);
        return userPhotosToPhotoInfo;

    }

    @Override
    public List<PhotoInfo> getUserPhotosByUid(Long id) {

        return userService.getUserById(id).getPhotos();
    }


    @Override
    public PhotoInfo replacePhoto(ReplacePhotoDto dto) {
        //替换相册   先删除再新增
        LocalUserInfo info = LocalUser.getUser();
        UserInfo u = GlobalController.getNowUser();
        Long uid = u.getId();
        Long pid = dto.getId();
        UserPhotos up = new UserPhotos();
        up.setId(pid);
        up = userPhotosMapper.selectOne(up);
        if (up == null || dto.getNewPhoto() == null) {
            throw new UserException(StatusCode.BAD_REQUEST);
        }
        up.setDeleted(1);
        long nowMilliSeconds = System.currentTimeMillis();
        long nowSeconds = nowMilliSeconds / 1000;
        up.setDeletedTime(nowSeconds);
        if (userPhotosMapper.updateByPrimaryKey(up) != 1) {
            throw new UserException(StatusCode.INTERNAL_SERVER_ERROR);
        }
        UserPhotos photo = new UserPhotos();
        photo.setCreatedTime(nowSeconds);
        photo.setPhoto(dto.getNewPhoto());
        photo.setSort(dto.getSort());
        photo.setUserId(uid);
        photo.setFirstImg(dto.getFirstImg());
        photo.setChecked(0);
        photo.setDeleted(0);
        photo.setDeletedTime(0L);
        photo.setUpdatedTime(nowSeconds);
        if (userPhotosMapper.insert(photo) != 1) {
            throw new UserException(StatusCode.INTERNAL_SERVER_ERROR);
        }
        photo = userPhotosMapper.selectOne(photo);
        //更新缓存
        if (rwRedisService.hhasKey(user_key, uid)) {
            UserInfo ui = (UserInfo) rwRedisService.hget(user_key, uid);
            ui.removePhoto(dto.getId());
            PhotoInfo photoToPhotoInfo = ConvertUtil.PhotoToPhotoInfo(photo);
            ui.addPhoto(photoToPhotoInfo);
            //更新完list按照sort排个序
            ui.getPhotos().sort((s1, s2) -> s1.getSort().compareTo(s2.getSort()));
            //更新用户token
            info.setUser(ui);
            tokenManagerService.updateUser(info);
            //更新用户信息
//            rwRedisService.opsForHash().put(user_key, uid, ui);
        } else {
            throw new UserException(StatusCode.USER_EXCEPTION);
        }
        if (dto.getFirstImg() == 1) {
            //更新mango
            //同时发消息给审核服务
            send(photo.getId(), photo.getPhoto());
			
			/* 异步处理
			 * UserEntity user = userDao.getUserById(uid);
			if(user==null) {
				throw new UserException(StatusCode.USER_EXCEPTION);
			}
			user.setFirstImg(dto.getNewPhoto());
			user.setChecked(0);
			userDao.updateUser(user);*/


            Update update = new Update().set("checked", TANTAN_STATUS_UNCHECKED)
                    .set("firstImg", dto.getNewPhoto());
            userDao.updateUserInfo(uid, update);
        }
        PhotoInfo pi = ConvertUtil.PhotoToPhotoInfo(photo);
        return pi;
    }

}
